/*------------------------------------------------------------------------
//                          Project CommonLib                           //
------------------------------------------------------------------------*/
#pragma once

#include <process.h>

typedef BOOL  (__stdcall *THREAD_FUNC_INIT)(void* pArg);
typedef int (__stdcall *THREAD_FUNC_RUN)( void* pArg);
typedef BOOL (__stdcall *THREAD_FUNC_WAIT)( void* pArg);
typedef void  (__stdcall *THREAD_FUNC_TERMINATE)(void* pArg);


#define DEFAULT_THREAD_STACK_SIZE	MB(4)

#include "CmMiniDumper.h"
//#include "Exception.h"



namespace Thread
{
        
    BOOL  __stdcall defaultInit(void* pArg);
    int __stdcall defaultRun(void* pArg);
    BOOL __stdcall defaultWait(void* pArg);
    void __stdcall defaultTer(void* pArg);;

    enum E_THREAD_STATE
    {
        
        eTHREAD_STATE_JUST_CREATE   = 0,
        eTHREAD_STATE_WAITTING      = 1,
        eTHREAD_STATE_RUN           = 2,
        eTHREAD_STATE_TERMINATE     = -1
    };

    //////////////////////////////////////////////////////////////////////////
    // BasicThread
    //////////////////////////////////////////////////////////////////////////
    class  BasicThread
    {
		enum {E_CHECK_FRAME_RATE_TIME = 1000};
    public:        
        BasicThread( const TCHAR* pName);
        virtual ~BasicThread();

        static int ExceptionHandler(EXCEPTION_POINTERS* pException, BasicThread* pThread)
        {
			//if (!SEH::g_ThreadDumper.Dump(pException, pThread))
			//{
			//	return EXCEPTION_EXECUTE_HANDLER;
			//}

			UNREFERENCED_PARAMETER( pException );
			UNREFERENCED_PARAMETER( pThread );
			return EXCEPTION_EXECUTE_HANDLER;	
        }


        virtual BOOL    			Init();
        virtual int   			Run();
        virtual void    			Terminate();
        virtual BOOL    			Wait();
        virtual void				CalcFrameRate();
		virtual void				Report();

		void						ForceDestroy();

        void						SetFunc(THREAD_FUNC_INIT pfInit, THREAD_FUNC_RUN pfRun, THREAD_FUNC_WAIT pfWait, THREAD_FUNC_TERMINATE pfTerminate);
		void						Suspend();
		void						Resume();

		
		const float					GetFrameRate()	const	{ return m_fCurrentFrameRate; }
		const TCHAR*				GetName()				{ return m_strName; }
		void						SetState( const E_THREAD_STATE& eState);
		E_THREAD_STATE				GetState() const		{ return m_eState;}
		
    private:
        THREAD_FUNC_INIT        	m_pfInit;
        THREAD_FUNC_RUN         	m_pfRun;
        THREAD_FUNC_WAIT        	m_pfWait;        
        THREAD_FUNC_TERMINATE   	m_pfTerminate;
        
		__PROPERTY(HANDLE,			Handle);
		__PROPERTY(DWORD,			ID);
		__PROPERTY_PTR(void,		Param);	
		

		//calc FrameRate
		DWORD						m_dwCurrentSpendTime;
		DWORD						m_dwPreviousTime;
		volatile float				m_fCurrentFrameRate;
		DWORD						m_dwFrameTime;
		DWORD						m_dwFrameCount;
		volatile E_THREAD_STATE		m_eState;
		
        TCHAR   m_strName[0xfff];        
    };


    //////////////////////////////////////////////////////////////////////////
    // ThreadPool
    //////////////////////////////////////////////////////////////////////////
    class ThreadPool
    {
        typedef stdext::hash_map<DWORD, BasicThread*> HASH_THREAD;
        typedef stdext::hash_map<DWORD, BasicThread*>::iterator IT_HASH_THREAD;

    public:
        ThreadPool();
        ~ThreadPool();


		void			Destroy();
        void			RegisterThread( BasicThread *pThread, BOOL bStart );
        void			UnRegisterThread( BasicThread *pThread );
		BOOL			ResumeThread(const DWORD& dwThreadID);
        BOOL			SuspendThread(const DWORD& dwThreadID);
		BasicThread*	GetThread( const DWORD& dwThreadID);
		void			Report();

	private:
        stdext::hash_map<DWORD, BasicThread*> m_hashHandle; 	
    };    

	//////////////////////////////////////////////////////////////////////////
	// SetThreadName
	//	http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.71).aspx
	//////////////////////////////////////////////////////////////////////////	
	#pragma pack(push,8)
	typedef struct tagTHREADNAME_INFO
	{
		DWORD		dwType;
		LPCSTR		szName;
		DWORD		dwThreadID;
		DWORD		dwFlags;

		tagTHREADNAME_INFO()
			:dwType(0x1000), dwFlags(0)
		{		
		}

	} THREADNAME_INFO;
	#pragma pack(pop)

	inline void _SetThreadName( const DWORD& dwThreadID, LPCSTR szThreadName)
	{
		THREADNAME_INFO info;
		info.szName		= szThreadName;
		info.dwThreadID = dwThreadID;

		__try
		{
			//::RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info);
			::RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), reinterpret_cast<const ULONG_PTR*>(&info) );
		}
		__except(EXCEPTION_CONTINUE_EXECUTION)
		{

		}
	}

	//////////////////////////////////////////////////////////////////////////
	// thread api
	//////////////////////////////////////////////////////////////////////////	
	HANDLE CreateCmThread( const TCHAR* pName, THREAD_FUNC_INIT pfInit, THREAD_FUNC_RUN pfRun, THREAD_FUNC_WAIT pfWait, THREAD_FUNC_TERMINATE pfTerminate
		,void* pParam, unsigned int* pID, BOOL bStart=TRUE);
	HANDLE CreateCmThread( BasicThread *pBasicThread, void* pParam, unsigned int* pID, BOOL bStart=TRUE);
	BOOL ResumeCmThread(const DWORD& dwThreadID);
	BOOL SuspendCmThread(const DWORD& dwThreadID);

}

/*------------------------------------------------------------------------

------------------------------------------------------------------------*/
 